package grex.Nodes;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2003</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */
import grex.BNFException;
import grex.ErrorManagement.ErrorManager;
import grex.Options;
import grex.Data.Prediction;
import grex.Data.PredictionContainer;
import grex.Nodes.GeneException;
import grex.Nodes.ICategoricalOperator;
import grex.Nodes.Node;

import java.util.ArrayList;
public class FuzzyCatVal extends Node implements IFuzzyNode, ICategoricalOperator{
  private static final int NROFCILDREN=1;
  private int varNr=-1;
  private double category=0;

  public FuzzyCatVal() throws BNFException{
    super(NROFCILDREN);

  }

  public synchronized void execute(Node parent,PredictionContainer data,int mode) throws GeneException {
        this.parent = parent;
        init();

        for (Prediction p : data.values()) {
            ArrayList<FuzzyMembershipClassPair> mValues = fuzzit(p.getInstance(), 1);
            double[] mSums = new double[environment.getNrOfTargetCategories()];
            
            double mVal =0;
            int classIndex = 0;
            for(FuzzyMembershipClassPair mc: mValues){
                mSums[((int)mc.classValue)]+=mc.membership;
            }
            
           /* for(int i = 0; i <mSums.length;i++){
                if(mSums[i]>mVal){
                    mVal=mSums[i];
                    classIndex=i;
                }
            }//*/
            p.setPrediction(-1);
            p.setSupport(mSums);
           // p.setProb(mVal);
            p.setLeaf(this);
        }
        //For each prediction in Predictioncontainer call fuzxit
        //Sum all memberships
        //Set prediction as highest
    }
public ArrayList<FuzzyMembershipClassPair> fuzzit(double[] instance, double membershipValue) throws GeneException{
        init();
        Node left = getChildren()[0];
        ArrayList<FuzzyMembershipClassPair> lResult;     
        double leftMembershipValue = membershipValue * (instance[varNr]==category?1:0);
        if (left instanceof IFuzzyNode) {
            lResult = ((IFuzzyNode) left).fuzzit(instance, leftMembershipValue);
        } else {//TargetPrediction
            lResult = new ArrayList<FuzzyMembershipClassPair>();
            lResult.add(new FuzzyMembershipClassPair(((FuzzyTarget) left).getValue(), leftMembershipValue));
        }
        return lResult;
    }  
  
  private void init(){
      if (varNr == -1) {
          varNr = environment.getRandomCategoricalColumnIndex();
          double internalVal = Options.rnd.nextDouble();
          category = environment.getInternalNumericalValue(varNr, internalVal,getFold());
      }
  }

  public void setVarNr(int varNr){
    this.varNr=varNr;
  }

  public int getVarNr() {
    init();
    return varNr;
  }

 public Object clone(){ ;
    FuzzyCatVal newFuzzyCatVal;
    try{
      newFuzzyCatVal = new FuzzyCatVal();
      newFuzzyCatVal.setFold(getFold());
      newFuzzyCatVal.setVarNr(varNr);
      newFuzzyCatVal.setCategory(category);
      newFuzzyCatVal.setOptions(ops);
      newFuzzyCatVal.setEnvironment(environment);
      cloneChildren(newFuzzyCatVal);
      newFuzzyCatVal.setParent(parent);
    }catch(grex.BNFException e){
      ErrorManager.getInstance().reportError(e);
      return null;
    }
    return newFuzzyCatVal;
  }
 
 
  /** @todo Om endast enn kategori finns kommer denna att volja lika ofta somma alla andra sammtidigt */

  public String toString(){        
            init();
            return environment.getVariableNames()[varNr]+"="+environment.getRealClassValue(varNr, category);
  }

    public double getCategory() {
        return category;
    }

    public void setCategory(double category) {
        this.category = category;
    }
}
